package grid;

import java.util.ArrayList;
import java.util.LinkedList;

import info.gridworld.grid.AbstractGrid;
import info.gridworld.grid.Location;

public class SparseBoundedGrid<E> extends AbstractGrid<E> {
	
	private LinkedList<OccupantInCol<E>>[] occupantArray;
	private int colLen;
	private int rowLen;
	
	public SparseBoundedGrid(int rows, int cols) {
		if( rows <= 0 )
			throw new IllegalArgumentException("rows<=0");
		if( cols <= 0 )
			throw new IllegalArgumentException("cols<=0");
		occupantArray = new LinkedList[rows];
		for(int i=0; i<rows; i++){
			occupantArray[i]=new LinkedList<OccupantInCol<E>>();
		}
		colLen = cols;
		rowLen = rows;
	}
	
	@Override
	public E get(Location loc) {
		if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
		for(OccupantInCol<E> a: occupantArray[loc.getRow()]){
			if(a.col == loc.getCol()){
				return a.occupant;
			}
		}
		return null;
	}

	@Override
	public int getNumCols() {
		return colLen;
	}

	@Override
	public int getNumRows() {
		return rowLen;
	}

	@Override
	public ArrayList<Location> getOccupiedLocations() {
		ArrayList<Location> locs = new ArrayList<Location>();
		for(int i=0; i<occupantArray.length; i++){
			for(OccupantInCol<E> b : occupantArray[i]){
				locs.add(new Location(i , b.col));
			}
		}
		return locs;
	}

	@Override
	public boolean isValid(Location loc) {
		return 0 <= loc.getRow() && loc.getRow() < getNumRows()
        && 0 <= loc.getCol() && loc.getCol() < getNumCols();
	}

	@Override
	public E put(Location loc, E obj) {
		if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
        if (obj == null)
            throw new NullPointerException("obj == null");

        // Add the object to the grid.
        E oldOccupant = get(loc);
        OccupantInCol<E> newOccupant = new OccupantInCol<E>();
        newOccupant.col=loc.getCol();
        newOccupant.occupant=obj;
        occupantArray[loc.getRow()].add(newOccupant);
        return oldOccupant;
	}

	@Override
	public E remove(Location loc) {
		if (!isValid(loc))
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
        
        // Remove the object from the grid.
        E r = get(loc);
        LinkedList<OccupantInCol<E>> oneRow = occupantArray[loc.getRow()];
        int i = 0;
        for( OccupantInCol<E> a : oneRow){
        	if( a.col == loc.getCol()){
        		oneRow.remove(i);
        		break;
        	}
        	i++;
        }
        	
        return r;
	}

}
